﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="LogEntryActioner.cs" company="DissingNelleman">
//   
// All rights reserved. </copyright>
// <summary>
//   The log entry actioner.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace ServiceLibrary.Actioners.Base
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    using NHibernate;

    using ServiceLibrary.Models.Base;
    using ServiceLibrary.Models.Domain;
    using ServiceLibrary.Services.Queries;
    using ServiceLibrary.Services.Results;

    /// <summary>
    /// The log entry actioner.
    /// </summary>
    public class LogEntryActioner
    {
        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="LogEntryActioner"/> class.
        /// </summary>
        /// <param name="hsession">
        /// The hsession.
        /// </param>
        /// <param name="activeUser">
        /// The active user.
        /// </param>
        public LogEntryActioner(ISession hsession, User activeUser)
        {
            this.ActiveUser = activeUser;
            this.Session = hsession;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the active user.
        /// </summary>
        private User ActiveUser { get; set; }

        /// <summary>
        /// Gets or sets the session.
        /// </summary>
        private ISession Session { get; set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The create log entry.
        /// </summary>
        /// <param name="editedObjectID">
        /// The edited object id.
        /// </param>
        /// <param name="text">
        /// The text.
        /// </param>
        /// <param name="type">
        /// The type.
        /// </param>
        public void CreateLogEntry(Guid editedObjectID, string text, Enums.LogEntryType type)
        {
            var entry = new LogEntry();
            entry.ID = Guid.NewGuid();
            entry.Editor = this.ActiveUser;
            entry.Timestamp = DateTime.Now;
            entry.EditedObjectID = editedObjectID;
            entry.ObjectType = type;
            entry.ActionType = Enums.LogEntryActionType.Create;
            entry.Text = text;
            this.Session.Save(entry);
        }

        /// <summary>
        /// The create log entry.
        /// </summary>
        /// <param name="editedObjectID">
        /// The edited object id.
        /// </param>
        /// <param name="text">
        /// The text.
        /// </param>
        /// <param name="type">
        /// The type.
        /// </param>
        /// <param name="actionType">
        /// The action type.
        /// </param>
        public void CreateLogEntry(Guid editedObjectID, string text, Enums.LogEntryType type, Enums.LogEntryActionType actionType)
        {
            var entry = new LogEntry();
            entry.ID = Guid.NewGuid();
            entry.Editor = this.ActiveUser;
            entry.Timestamp = DateTime.Now;
            entry.EditedObjectID = editedObjectID;
            entry.ObjectType = type;
            entry.ActionType = actionType;
            entry.Text = text;
            this.Session.Save(entry);
        }

        #endregion

        #region Methods

        /// <summary>
        /// The execute search query.
        /// </summary>
        /// <param name="logEntryQuery">
        /// The log entry query.
        /// </param>
        /// <returns>
        /// The <see cref="IResult"/>.
        /// </returns>
        internal IResult ExecuteSearchQuery(LogEntryQuery logEntryQuery)
        {
            var aBase = new ActionerBase(null, null);

            SearchSettings settings = logEntryQuery.Settings;
            var result = new LogEntryResult();

            IQueryOver<LogEntry, LogEntry> search = this.Session.QueryOver<LogEntry>();
            aBase.ApplyDefaultCriterias(logEntryQuery.Settings, search);

            if (logEntryQuery.ActionType.HasValue)
            {
                search = search.Where(x => x.ActionType == logEntryQuery.ActionType.Value);
            }

            if (logEntryQuery.ObjectType.HasValue)
            {
                search = search.Where(x => x.ObjectType == logEntryQuery.ObjectType.Value);
            }

            if (logEntryQuery.EditedObjectID.HasValue && logEntryQuery.EditedObjectID.Value != Guid.Empty)
            {
                search = search.Where(x => x.EditedObjectID == logEntryQuery.EditedObjectID.Value);
            }

            if (logEntryQuery.EditorID.HasValue && logEntryQuery.EditorID.Value != Guid.Empty)
            {
                User editor = this.Session.Get<User>(logEntryQuery.EditorID.Value);

                if (editor != null)
                {
                    search = search.Where(x => x.Editor == editor);
                }
            }

            result.TotalRowCount = search.RowCount();

            search = search.OrderBy(x => x.Timestamp).Desc;

            IList<LogEntry> list = aBase.ApplySkipAndTake(settings, search);

            if (list.Any())
            {
                foreach (LogEntry logEntry in list)
                {
                    result.List.Add(Services.Dto.LogEntry.Convert(logEntry));
                }
            }

            return result;
        }

        #endregion
    }
}